﻿using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Abp.Authorization.Roles;
using Microsoft.EntityFrameworkCore;
using Abp.Zero.EntityFrameworkCore;
using KelonProud.Administration.Domain.Authorization;
using KelonProud.Administration.Domain.Configuration;
using KelonProud.MultiTenancy;
using Abp.EntityHistory;
using KelonProud.Administration.Domain.Organizations;
using KelonProud.Administration.Logs;
using KelonProud.Administration.Logs.Domain;
using KelonProud.QuickQuery.Domain;
using KelonProud.TableManagement.Domain;

namespace KelonProud.EntityFrameworkCore
{
    public class KelonProudDbContext : AbpZeroDbContext<Tenant, Role, User, KelonProudDbContext>
    {
        /* Define a DbSet for each entity of the application */


        //  public new DbSet<KelonProudUserRole> UserRoles { get; set; }

        #region  admin
        public new virtual DbSet<KelonProudOrganizationUnit> OrganizationUnits { get; set; }
        public virtual DbSet<Navigation> Navigations { get; set; }
        public virtual DbSet<NavigationRole> NavigationRoles { get; set; }
        public virtual DbSet<AuthorityRole> AuthorityRoles { get; set; }
        public virtual DbSet<EditionNavigation> EditionNavigations { get; set; }
        public virtual DbSet<KelonProudIcon> DragonJetIcons { get; set; }
        public virtual DbSet<RolePermissionSetting> RolePermissionSettings { get; set; }
        public virtual DbSet<Attachment> Attachments { get; set; }

        #region logs

        public new virtual DbSet<KelonEntityChange> EntityChanges { get; set; }
        public new virtual DbSet<KelonEntityChangeSet> EntityChangeSets { get; set; }
        public new virtual DbSet<KelonEntityPropertyChange> EntityPropertyChanges { get; set; }
        #endregion
        #endregion

        #region tables 
        public virtual DbSet<KelonDataBase> KelonDataBases { get; set; }
        public virtual DbSet<KelonTable> KelonTables { get; set; }
        public virtual DbSet<TableCategory> TableCategorys { get; set; }
        public virtual DbSet<KelonTableColumn> KelonTableColumns { get; set; }
        public virtual DbSet<QueryGrid> QueryGrids { get; set; }
        public virtual DbSet<QueryGridColumn> QueryGridColumns { get; set; }
        public virtual DbSet<QueryCommand> QueryCommands { get; set; }
        #endregion

        public KelonProudDbContext(DbContextOptions<KelonProudDbContext> options)
            : base(options)
        {
        }

        public new IKelonEntityHistoryHelper EntityHistoryHelper { get; set; }

        public override int SaveChanges()
        {
            var changeSet = EntityHistoryHelper?.CreateEntityChangeSet(ChangeTracker.Entries().ToList());

            var result = base.SaveChanges();

            EntityHistoryHelper?.Save(changeSet);

            return result;
        }

        public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
        {
            var changeSet = EntityHistoryHelper?.CreateEntityChangeSet(ChangeTracker.Entries().ToList());

            var result = await base.SaveChangesAsync(cancellationToken);

            if (EntityHistoryHelper != null)
            {
                await EntityHistoryHelper.SaveAsync(changeSet);
            }

            return result;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            //var loggerFactory = new LoggerFactory();
            //loggerFactory.AddProvider(new EfLoggerProvider());
            //optionsBuilder.UseLoggerFactory(loggerFactory);

            base.OnConfiguring(optionsBuilder);
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
          //   modelBuilder.OnExpandDbContext();


            modelBuilder.ChangeAbpTablePrefix<Tenant, Role, User>("Kp");

            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<NavigationRole>(b =>
            {
                b.HasIndex(i => new { i.NavigationId, i.RoleId });
            });

            modelBuilder.Entity<AuthorityRole>(b =>
            {
                b.HasIndex(i => new { i.AuthorityId, i.RoleId });
            });

            modelBuilder.Entity<EditionNavigation>(b =>
            {
                b.HasIndex(i => new { i.NavigationId, i.EditionId });
            });
        }
    }
}
